<template>
  <div ref="containerA" :class= "$style.containerA" @mousedown="startDrag" @touchstart.passive="startDrag">
    <div ref="elementB" :class="$style.elementB"
      :style="{
        transform: `translate(${offset.x}px, ${offset.y}px)`,
        transition: isDragging ? 'none' : 'transform 0.3s ease'
      }"
    >
      <slot></slot>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'

interface Position {
  x: number
  y: number
}

const emit=defineEmits<{
  (e:'ondrag',offset:Position):void
  (e:'ondragend'):void
  (e:'ondragstart'):void
}>()

const containerA = ref<HTMLElement | null>(null)
const elementB = ref<HTMLElement | null>(null)
const isDragging = ref(false)
const startPos = ref<Position>({ x: 0, y: 0 })
const offset = ref<Position>({ x: 0, y: 0 })
const centerOffset = ref<Position>({ x: 0, y: 0 })

// 计算B元素在A容器中的中心位置
const calculateCenterOffset = (): void => {
  if (!containerA.value || !elementB.value) return
  
  const containerRect = containerA.value.getBoundingClientRect()
  const elementRect = elementB.value.getBoundingClientRect()
  
  centerOffset.value = {
    x: (containerRect.width - elementRect.width),
    y: (containerRect.height - elementRect.height),
  }
}

const startDrag = (e: MouseEvent | TouchEvent): void => {
  isDragging.value = true
  emit('ondragstart')
  
  // 获取初始触点位置
  const clientX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX
  const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY
  
  if (!containerA.value) return
  const containerRect = containerA.value.getBoundingClientRect()
  
  // 计算相对于容器中心的偏移
  startPos.value = {
    x: clientX - containerRect.left - centerOffset.value.x,
    y: clientY - containerRect.top - centerOffset.value.y
  }

  // 添加事件监听
  window.addEventListener('mousemove', handleDrag)
  window.addEventListener('touchmove', handleDrag, { passive: false })
  window.addEventListener('mouseup', endDrag)
  window.addEventListener('touchend', endDrag)
}

const handleDrag = (e: MouseEvent | TouchEvent): void => {
  if (!isDragging.value || !containerA.value) return
  
  e.preventDefault()

  const clientX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX
  const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY
  
  const containerRect = containerA.value.getBoundingClientRect()
  
  // 计算相对于容器中心的偏移
  offset.value = {
    x: clientX - containerRect.left - centerOffset.value.x,
    y: clientY - containerRect.top - centerOffset.value.y
  }

  emit('ondrag', offset.value)
}

const endDrag = (): void => {
  isDragging.value = false
  emit('ondragend')
  offset.value = { x: 0, y: 0 } // 返回中心位置
  
  // 移除事件监听
  window.removeEventListener('mousemove', handleDrag)
  window.removeEventListener('touchmove', handleDrag)
  window.removeEventListener('mouseup', endDrag)
  window.removeEventListener('touchend', endDrag)
}

onMounted(() => {
  calculateCenterOffset()
  window.addEventListener('resize', calculateCenterOffset)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', calculateCenterOffset)
  endDrag() // 清理事件监听
})

</script>

<style module>
.containerA {
  position: relative;
  width: 8em;
  height: 8em;
  background-color: rgba(255,255,255,0.3);
  cursor: pointer;
  pointer-events: auto;
  border-radius: 4em;
  user-select: none !important;
  -webkit-user-select: none !important;
  -webkit-touch-callout: none !important;
}

.elementB {
  position: absolute;
  width: 4em;
  height: 4em;
  background-color: rgba(255,255,255,0.5);
  border-radius: 2em;
  user-select: none;
  touch-action: none;
  will-change: transform; /* 优化动画性能 */
  top: 2em;
  left: 2em;
}
</style>